package com.cskaoyan.wordmemorize.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.cskaoyan.wordmemorize.converter.UserConverter;
import com.cskaoyan.wordmemorize.dao.entity.*;
import com.cskaoyan.wordmemorize.dao.mapper.*;
import com.cskaoyan.wordmemorize.dto.admin.PageDTO;
import com.cskaoyan.wordmemorize.dto.app.*;
import com.cskaoyan.wordmemorize.request.PageRequest;
import com.cskaoyan.wordmemorize.request.UserRemindCommand;
import com.cskaoyan.wordmemorize.service.UserService;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;

import java.time.LocalTime;
import java.util.List;


@Service
public class UserServiceImpl implements UserService {

    @Resource
    private UserMapper userMapper;

    @Resource
    private UserConverter userConverter;

    @Resource
    private UserRemindMapper userRemindMapper;


    @Resource
    private UserVocBoundStatisticsMapper userVocBoundStatisticsMapper;

    @Resource
    private LevelMapper levelMapper;

    @Override
    public UserDTO getUserInfo(Long userId) {
        // 查询用户基本信息
        UserDO userDO = userMapper.getUserInfo(userId);
        return userConverter.userDO2DTO(userDO);
    }

    @Override
    public NextLevelDTO getUserNextDTO(Long userId) {
        // 查询当前用户等级和签到情况，计算距离下次升级剩余天数
        // 1. 查询用户当前等级
        UserDO userDO = userMapper.selectById(userId);
        if (userDO == null) {
            // 用户不存在，返回空对象而非空值
            NextLevelDTO emptyDto = new NextLevelDTO();
            emptyDto.setRemainDays(0);
            emptyDto.setSignType(0);
            return emptyDto;
        }

        // 2. 查询等级表，找到下一级等级
        LambdaQueryWrapper<LevelDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.gt(LevelDO::getLevelValue, userDO.getLevelValue());
        wrapper.orderByAsc(LevelDO::getLevelValue);
        wrapper.last("LIMIT 1"); // 限制只返回一条记录，解决TooManyResultsException

        LevelDO nextLevel = levelMapper.selectOne(wrapper);
        if (nextLevel == null) {
            // 已达最大等级，返回空对象而非空值
            NextLevelDTO emptyDto = new NextLevelDTO();
            emptyDto.setRemainDays(0);
            emptyDto.setSignType(0);
            return emptyDto;
        }

        // 3. 计算剩余天数
        NextLevelDTO dto = userConverter.levelDO2NextLevelDTO(nextLevel);

        // 简化实现，固定值或从配置获取
        int remainDays = 7; // 默认值，可以根据业务需求调整

        dto.setRemainDays(remainDays);
        dto.setSignType(nextLevel.getCheckInType() != null ? nextLevel.getCheckInType() : 0);

        return dto;
    }

    @Override
    public DisplayUserLevelDTO getUserLevelInfo(Long userId) {
        // 查询当前等级与未达等级，组装DisplayUserLevelDTO
        UserDO userDO = userMapper.selectById(userId);
        if (userDO == null) return new DisplayUserLevelDTO();
        Integer userLevelValue = userDO.getLevelValue();
        // 当前等级
        LambdaQueryWrapper<LevelDO> nowLevelWrapper = new LambdaQueryWrapper<>();
        nowLevelWrapper.le(LevelDO::getLevelValue, userLevelValue);
        nowLevelWrapper.orderByAsc(LevelDO::getLevelValue);
        List<LevelDO> nowLevels = levelMapper.selectList(nowLevelWrapper);
        // 未达等级
        LambdaQueryWrapper<LevelDO> upperLevelWrapper = new LambdaQueryWrapper<>();
        upperLevelWrapper.gt(LevelDO::getLevelValue, userLevelValue);
        upperLevelWrapper.orderByAsc(LevelDO::getLevelValue);
        List<LevelDO> upperLevels = levelMapper.selectList(upperLevelWrapper);
        DisplayUserLevelDTO dto = new DisplayUserLevelDTO();
        dto.setNowLevel(userConverter.levelDOsLevelPageDTOs(nowLevels));
        dto.setUpperLevel(userConverter.levelDOsLevelPageDTOs(upperLevels));
        return dto;
    }

    @Override
    public void updateVocCountOfDay(Long userId, Integer count) {
        // 更新用户每天计划学习的单词量
        UserDO userDO = new UserDO();
        userDO.setId(userId);
        userDO.setVocCountOfDay(count);
        userMapper.updateById(userDO);
    }

    @Override
    public void updateUserRemind(UserRemindCommand command, Long userId) {
        // 先查是否已有提醒设置
        LambdaQueryWrapper<UserRemindDO> query = new LambdaQueryWrapper<>();
        query.eq(UserRemindDO::getUserId, userId); // 根据当前用户id去查
        UserRemindDO remindDO = userRemindMapper.selectOne(query);

        // 目前来说，如果登录用户无误，那么一定会获取到正确ID的，不太可能需要走到这步，留着以防万一
        if (remindDO == null) {
            // 新增
            remindDO = userConverter.userRemindCommand2DO(command);
            userRemindMapper.insert(remindDO);
        } else {
            // 更新
            remindDO.setRemindTime(LocalTime.parse(command.getRemindTime())); // 保证类型为LocalTime
            userRemindMapper.updateById(remindDO);
        }
    }


    @Override
    public UserRemindDTO getUserRemind(Long userId) {
        // 查询用户提醒设置
        LambdaQueryWrapper<UserRemindDO> query = new LambdaQueryWrapper<>();
        query.eq(UserRemindDO::getUserId, userId);
        UserRemindDO remindDO = userRemindMapper.selectOne(query);
        if (remindDO == null) {
            return new UserRemindDTO();
        }
        // 传入第二个参数为提醒描述，这里用默认值
        return userConverter.userRemindDO2DTO(remindDO, "学习提醒");
    }

    // TODO: 实现用户消息提醒功能
    @Override
    public void messageRemind() {
    }

    // 已删除 无需实现
    // 获取用户单词上限日志
    @Override
    public PageDTO<DisplayUserVocBoundLogDTO> getUserVocBoundLog(PageRequest pageRequest, Long userId) {
//        // 分页查询用户单词上限变化明细
//        // 设置默认分页参数，避免空指针异常
//        int pageNum = 1;
//        int count = 10;
//
//        if (pageRequest != null) {
//            if (pageRequest.getPageNum() != null) {
//                pageNum = pageRequest.getPageNum();
//            }
//            if (pageRequest.getCount() != null) {
//                count = pageRequest.getCount();
//            }
//        }
//
//        Page<UserVocBoundLogDO> page = new Page<>(pageNum, count);
//        LambdaQueryWrapper<UserVocBoundLogDO> query = new LambdaQueryWrapper<>();
//        query.eq(UserVocBoundLogDO::getUserId, userId);
//
//        // 安全地处理关键词
//        if (pageRequest != null && pageRequest.getKeyword() != null && !pageRequest.getKeyword().isEmpty()) {
//            query.like(UserVocBoundLogDO::getDescription, pageRequest.getKeyword());
//        }
//
//        page = userVocBoundLogMapper.selectPage(page, query);
//        List<DisplayUserVocBoundLogDTO> dtoList = userConverter.userVocBoundLogDTOs2DisplayDTOs(page.getRecords());
//        return userConverter.userVocBoundLogPage2PageDTO(dtoList, page.getTotal());
        return null;
    }

    @Override
    public UserVocBoundStatisticsDTO getUserVocBoundStatistics(Long userId) {
        // 查询用户单词上限统计
        LambdaQueryWrapper<UserVocBoundStatisticsDO> query = new LambdaQueryWrapper<>();
        query.eq(UserVocBoundStatisticsDO::getUserId, userId);
        UserVocBoundStatisticsDO statisticsDO = userVocBoundStatisticsMapper.selectOne(query);
        if (statisticsDO == null) {
            return new UserVocBoundStatisticsDTO();
        }
        return userConverter.userVocBoundStatisticsDO2DisplayDTO(statisticsDO);
    }


    @Override
    public UserPageDTO getUserPage(Long userId) {
        // 查询用户基本信息
        UserDO userDO = userMapper.selectById(userId);
        // 查询提醒时间
        LambdaQueryWrapper<UserRemindDO> remindQuery = new LambdaQueryWrapper<>();
        remindQuery.eq(UserRemindDO::getUserId, userId);
        UserRemindDO remindDO = userRemindMapper.selectOne(remindQuery);
        // 查询单词上限统计
        LambdaQueryWrapper<UserVocBoundStatisticsDO> vocBoundQuery = new LambdaQueryWrapper<>();
        vocBoundQuery.eq(UserVocBoundStatisticsDO::getUserId, userId);
        UserVocBoundStatisticsDO vocBoundDO = userVocBoundStatisticsMapper.selectOne(vocBoundQuery);
        // 组装DTO
        UserPageDTO dto = new UserPageDTO();
        if (userDO != null) {
            dto.setVocCountOfDay(userDO.getVocCountOfDay());
            dto.setReSignCard(userDO.getHasSignCard());
        }
        if (vocBoundDO != null) {
            dto.setTotalVocBound(vocBoundDO.getTotal());
            dto.setFreeVocBound(vocBoundDO.getFree());
            dto.setPayVocBound(vocBoundDO.getPay());
        }
        if (remindDO != null && remindDO.getRemindTime() != null) {
            dto.setRemindTime(remindDO.getRemindTime().toString());
        }
        return dto;
    }
}
